home *** CD-ROM | disk | FTP | other *** search
- /*
- 89/03/02: ERS: added the "mode" argument for MS-DOS/Unix
- compatibility. Added prototypes for GNU C.
-
- fixed spawnve: the original didn't pass the command tail
- correctly, nor did it handle errno right. Also, this version
- passes args in the environment as well as the command line,
- using the ARGV= mechanism supported by crt0.s
-
- Written 89/01/10 by ERS. Original version Copyright (c) 1988 by
- Memorial University of Newfoundland. This version is based upon
- that original, but is substantially different. (In fact, there
- probably isn't a single line of the original left.)
- */
-
- #include <stdarg.h>
- #include <process.h>
- #include <param.h>
- #include <errno.h>
- #include <osbind.h>
- #include <stdlib.h>
- #include <time.h>
- #include <string.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include "lib.h"
-
- extern char **environ;
-
- clock_t _child_runtime;
- clock_t _sys_runtime;
-
- #define TOS_ARGS 126
- static char cmd[TOS_ARGS+1];
-
- /*
- * FIXME: currently mode == P_OVERLAY doesn't work as advertised, i.e. it
- * doesn't free whatever memory it can.
- */
-
- int
- spawnve(mode, _path, argv, envp)
- int mode;
- const char *_path;
- char * const *argv;
- char * const *envp;
- {
- void __exit(long);
- static char path[MAXPATHLEN];
- size_t cmlen;
- size_t enlen = 0;
- char *p;
- char *s, *t;
- char *env;
- clock_t _child_start;
- long rval;
-
- if (mode != P_WAIT && mode != P_OVERLAY && mode != P_NOWAIT) {
- errno = EINVAL;
- return -1;
- }
- (void)unx2dos(_path, path); /* convert filename, if necessary */
- if (!envp)
- envp = environ;
-
- /* count up space needed for environment */
- for(cmlen = 0; argv[cmlen]; cmlen++)
- enlen += strlen(argv[cmlen]) + 1;
- for(cmlen = 0; envp[cmlen]; cmlen++)
- enlen += strlen(envp[cmlen]) + 1;
- enlen += 32; /* filler for stuff like ARGV= and zeros */
-
- if ((env = (char *)Malloc((long)enlen)) == NULL) {
- errno = ENOMEM;
- return -1;
- }
- s = env;
- while ((p = *envp) != 0) {
- /*
- * NOTE: in main.c, we converted the PATH environment variable into
- * POSIX form. Here, we convert back into gulam form. Note that the
- * new variable will be shorter than the old, so space is not a problem.
- */
- if (!strncmp(p, "PATH=", 5)) {
- strncpy(s, p, 5); s += 5; p += 5;
- while (*p) {
- if (!strncmp(p, "/dev/", 5) && p[5]) {
- *s++ = p[5];
- *s++ = ':';
- p += 6;
- } else if (*p == ':') {
- *s++ = ','; p++;
- } else if (*p == '/') {
- *s++ = '\\'; p++;
- } else {
- *s++ = *p++;
- }
- }
- } else {
- while(*p)
- *s++ = *p++;
- }
- *s++ = '\0';
- envp++;
- }
- strcpy(s, "ARGV=");
- s += 6; /* s+=sizeof("ARGV=") */
-
- /* copy argv[0] first (because it doesn't go into the command line */
- if (argv && *argv) {
- for (p = *argv; *p; )
- *s++ = *p++;
- *s++ = '\0';
- }
-
- bzero(t = cmd, sizeof(cmd));
-
- /* s points at the environment's copy of the args */
- /* t points at the command line copy to be put in the basepage */
-
- cmlen = 0; /* was missing -- mmn, 92/03/10 */
- if (argv && *argv) {
- t++;
- while (*++argv) {
- p = *argv;
- while (*p) {
- if (cmlen <= TOS_ARGS) {
- *t++ = *p; cmlen++;
- }
- *s++ = *p++;
- }
- if (cmlen <= TOS_ARGS && *(argv+1)) {
- *t++ = ' '; cmlen++;
- }
- *s++ = '\0';
- }
- /* *cmd = (char) cmlen; NOT ANY MORE */
- }
-
- /* tie off environment */
- *s++ = '\0';
- *s = '\0';
-
- /* signal Extended Argument Passing */
- *cmd = 0x7f;
-
- /* close files marked for close on exec */
- for(cmlen = 0; cmlen < __NHANDLES; cmlen++)
- if(__open_stat[cmlen].eclose)
- (void)close(cmlen + __SMALLEST_VALID_HANDLE);
-
- _child_start = clock();
-
- /* MiNT and MicroRTX support background processes with Pexec(100,...) */
- cmlen = (mode == P_NOWAIT) ? 100 : PE_LOADGO;
-
- if ((rval = Pexec((int)cmlen, path, cmd, env)) < 0)
- {
- errno = -rval;
- cmlen = -1;
- }
- if (mode == P_OVERLAY)
- __exit(rval);
-
- (void)Mfree(env);
- _child_runtime += (clock() - _child_start);
- return rval;
- }
-
- int
- spawnv(mode, path, argv)
- int mode;
- const char *path;
- char * const *argv;
- {
- return spawnve(mode, path, argv, environ);
- }
-
- #ifdef __STDC__
- int spawnle(int mode, const char *path, ...)
- #else
- int spawnle(mode, path)
- int mode;
- const char *path;
- #endif
- {
- va_list args;
- char ***envp;
-
- va_start(args, path);
-
- for (envp = (char ***) args ; *envp ; envp++)
- ;
- return spawnve(mode, path, (char **)args, *(envp+1));
- }
-
- #ifdef __STDC__
- int spawnl(int mode, const char *path, ...)
- #else
- int spawnl(mode, path)
- int mode;
- const char *path;
- #endif
- {
- va_list args;
-
- va_start(args, path);
- return spawnve(mode, path, (char **)args, environ);
- }
-